#include "rclcpp/rclcpp.hpp"
#include "bs_complex/msg/complex_num.hpp"
#include "bs_norm/srv/norm.hpp"

#include <chrono>
#include <cstdlib>
#include <memory>

#include <ctime>

using namespace std::chrono_literals;

int rand_int(const int minValue,const int maxValue){return (rand()%(maxValue - minValue +1)) + minValue;}

int main(int argc, char **argv)
{
  rclcpp::init(argc, argv);
  srand(time(NULL));

  std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("norm_client");
  rclcpp::Client<bs_norm::srv::Norm>::SharedPtr client = node->create_client<bs_norm::srv::Norm>("complex_norm");

  auto request = std::make_shared<bs_norm::srv::Norm::Request>();
  auto complex = bs_complex::msg::ComplexNum();
  complex.re = rand_int(0,20e3)/1e3;
  complex.im = rand_int(0,20e3)/1e3;
  request->complex = complex;
  RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "request: re=%f im=%f", complex.re, complex.im);

  while (!client->wait_for_service(1s)) 
  {
    if (!rclcpp::ok()) 
    {
      RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
      return 0;
    }
    RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");
  }

  auto result = client->async_send_request(request);
  // Wait for the result.
  if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS)
  {
    RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "norm: %f", result.get()->norm);
  } else {
    RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service add_two_ints");
  }

  rclcpp::shutdown();
  return 0;
}